import { MiddlewareCreater } from 'f2e-server'
import { Route, out } from 'f2e-serve'
import { ERRORS } from './utils/common'
import { getLoginUser } from './utils/users'
import { listen$sse } from './listen'
import config from './config'
import * as actions from './actions'
import { do_upload, download, begin_upload } from './actions/upload'
import { FetchAPI } from './interfaces'
import { DEFAULT_ENCRYPT_KEY, doEncode, doDecode } from './global'

const prefix = config.publicPath.replace(/^\/+/g, '')
const creater: MiddlewareCreater = (conf) => {
    const renderFetchAPI = (route: Route) => ([key, fn]: [string, FetchAPI]) => {
      route.on(`${prefix}/${key}`, out.JsonOut(async function (req) {
          const loginUser = await getLoginUser(req)
          if (!loginUser) {
            const { login } = config.server.check
              return doEncode({
                  error: ERRORS.NOT_LOGIN,
                  location: login
              }, null)
          }
          try {
            const result = await fn(doDecode(req?.body, loginUser.token) || req?.data, { loginUser, req })
            return doEncode(result, loginUser.token)
          } catch (e) {
            console.log(e)
            return doEncode({
              error: ERRORS.UNKNOWN
            }, loginUser.token)
          }
      }, conf))
    }

    /** 需要前置的请求 */
    const route0 = new Route()
    Object.entries({ do_upload }).forEach(renderFetchAPI(route0))

    /** 参数解析后的API请求 */
    const route1 = new Route()
    route1.on(new RegExp(prefix ? `^${prefix}/download/.*` : '^download/.*'), function (req, resp) {
      download(req, resp, conf)
    })
    route1.on(`${prefix}/listen`, out.ServerSent(listen$sse, { ...conf, interval: 0 }))
    route1.on(`${prefix}/config.js`, out.Base('.js')(async (req) => {
      const loginUser = await getLoginUser(req)
      return `__CONFIG__ = ${JSON.stringify({
        ...(config.client || {}),
        encrypt_key: loginUser?.token || DEFAULT_ENCRYPT_KEY,
      })};`
    }, conf))
    Object.entries({ ...actions, begin_upload }).forEach(renderFetchAPI(route1))

    return {
        beforeRoute: (pathname, req, resp) => route0.execute(pathname, req as any, resp),
        onRoute: route1.execute,
    }
}

export default creater
